package co.fitstart.mobile.service.impl;

import java.util.Date;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.demo2do.core.BusinessException;
import com.demo2do.core.persistence.GenericDaoSupport;
import com.demo2do.core.utils.DateFormatUtils;

import co.fitstart.entity.coupon.Coupon;
import co.fitstart.entity.coupon.CouponBatch;
import co.fitstart.entity.coupon.CreditCouponBatch;
import co.fitstart.entity.credit.Credit;
import co.fitstart.entity.credit.CreditTransaction;
import co.fitstart.entity.credit.order.CreditOrder;
import co.fitstart.entity.credit.product.CreditProduct;
import co.fitstart.entity.credit.product.CreditProductType;
import co.fitstart.entity.user.Student;
import co.fitstart.entity.user.User;
import co.fitstart.entity.user.UserAddress;
import co.fitstart.mobile.dao.support.CreditDaoSupport;
import co.fitstart.mobile.dao.support.StudentDaoSupport;
import co.fitstart.mobile.handler.SmsSender;
import co.fitstart.mobile.service.CreditTradingService;

/**
 * @author Guangli Yan
 *
 */
@Service("creditTradingService")
public class CreditTradingServiceImpl implements CreditTradingService {
    @Autowired
    private GenericDaoSupport genericDaoSupport;

    @Autowired
    private StudentDaoSupport studentDaoSupport;

    @Autowired
    private CreditDaoSupport creditDaoSupport;

    @Autowired
    private SmsSender smsSender;

    /* (non-Javadoc)
     * @see co.fitstart.mobile.service.CreditTradingService#doExchange(java.lang.Long, java.lang.Long, java.lang.Integer, co.fitstart.entity.user.User)
     */
    public Integer doExchange(Long userAddressId, Long creditProdcutionId, Integer amount, User user) {
        CreditProduct creditProduct = genericDaoSupport.load(CreditProduct.class, creditProdcutionId);

        UserAddress userAddress = null;

        if (creditProduct.getType() == CreditProductType.PRODUCT) {
            userAddress = genericDaoSupport.load(UserAddress.class, userAddressId);
        }

        Student student = studentDaoSupport.load(user);

        Credit credit = creditDaoSupport.generallyLoad(user);

        // 1.validate data.
        this.validate(user, creditProduct, userAddress, credit ,amount);

        // 2.the type of credit coupon.
        if (creditProduct.getType() == CreditProductType.COUPON) {
            CreditCouponBatch creditCouponBatch = genericDaoSupport.load(CreditCouponBatch.class, creditProduct.getCreditCouponBatchId());
            
            //1.eidt CouponBatch、CreditCoupon's claimed amount & release amount
            CouponBatch couponBatch = creditCouponBatch.getCouponBatch();
            
            genericDaoSupport.update(couponBatch.editClaimedAmount(amount).editReleaseAmount(amount));
            genericDaoSupport.update(creditCouponBatch.editClaimedAmount(amount).editReleaseAmount(amount));
            
            //2.create new Coupon
            Long userId = user.getId();
            StringBuffer couponCodeBuffer = new StringBuffer();
            for(int i=0; i<amount; i++) {
            	Coupon coupon = new Coupon(couponBatch);
                coupon.generateCode();
                genericDaoSupport.save(coupon.bindUser(userId));
                couponCodeBuffer.append(coupon.getCode()+",");
            }
            String couponCode = couponCodeBuffer.length() > 0 ? couponCodeBuffer.substring(0, couponCodeBuffer.length()-1) : null;
            
            //3.modify the attribute of product.
            creditProduct.exchange(amount);
            genericDaoSupport.update(creditProduct);
            
            //4.edit credit's credit value
            int usedCredit = creditCouponBatch.getCreditValue();
            genericDaoSupport.update(credit.useCredit(usedCredit));
            genericDaoSupport.update(user.useCredit(usedCredit));

            //5.create a new creditTransaction
            CreditTransaction creditTransaction = new CreditTransaction(credit);
            genericDaoSupport.save(creditTransaction.exchangeCoupon(creditCouponBatch));
            
            //6.create credit order
            CreditOrder creditOrder = new CreditOrder();
            
            // digits random number between 0 (inclusive) ~ 100 (exclusive)
            String randomNumber = String.format("%02d", Double.valueOf(Math.floor(Math.random() * 100)).intValue());
            
            // Generate code with 20 digits total
            String creditOrderNo = new StringBuilder().append("CO").append(randomNumber)
                    .append(DateFormatUtils.format(new Date(), "yyMMddHHmmssSSS")).toString();
            
            creditOrder.initCoupon(creditOrderNo, creditProduct, amount ,student, couponCode, user);
             
             Long creditOrderId = (Long) genericDaoSupport.save(creditOrder);
             
             return creditOrderId.intValue();
        }

        // 3.the type of credit product.
        else if (creditProduct.getType() == CreditProductType.PRODUCT) {
            // 1.create creditOrder
            CreditOrder creditOrder = new CreditOrder();
            
            // digits random number between 0 (inclusive) ~ 100 (exclusive)
            String randomNumber = String.format("%02d", Double.valueOf(Math.floor(Math.random() * 100)).intValue());
            
            // Generate code with 20 digits total
            String creditOrderNo = new StringBuilder().append("CO").append(randomNumber)
                    .append(DateFormatUtils.format(new Date(), "yyMMddHHmmssSSS")).toString();
            
            creditOrder.initProduct(creditOrderNo, creditProduct, userAddress, amount, student);
            
            Long creditOrderId = (Long) genericDaoSupport.save(creditOrder);
            
            // 2.create new creditTransaction
            CreditTransaction creditTransaction = new CreditTransaction(credit);
            
            creditTransaction.exchangeCreditProduct(creditProduct);
            
            genericDaoSupport.save(creditTransaction);
            
            // 3. modify the attribute of product.
            creditProduct.exchange(amount);
            genericDaoSupport.update(creditProduct);
            
            // 4. update credit of user.
            int usedCredit = creditProduct.getCurrentPrice().intValue();
            genericDaoSupport.update(credit.useCredit(usedCredit));
            genericDaoSupport.update(user.useCredit(usedCredit));
            
            // 5. send message
            smsSender.sendSaleProductNotice("13162193559", "积分兑换订单");
            
             return creditOrderId.intValue();
        }
        
        return null;
    }

    /**
     * @param user
     * @param creditProduct
     * @param userAddress
     * @param credit
     * @param amount 
     */
    private void validate(User user, CreditProduct creditProduct, UserAddress userAddress, Credit credit, Integer amount) {

        int currentPrice = creditProduct.getCurrentPrice().intValue();
        
        if (credit == null || credit.getAvailableCredit() - (currentPrice * amount) < 0) {
            throw new BusinessException("积分不足");
        }

        if (creditProduct.getAmount() <= 0) {
            throw new BusinessException("兑换失败：该商品已被兑换完");
        } else if (creditProduct.getAmount() < amount) {
            throw new BusinessException("兑换失败：兑换数量大于剩余商品数量");
        }

        if (creditProduct.getType() == CreditProductType.COUPON) {
            
            CreditCouponBatch creditCouponBatch = genericDaoSupport.load(CreditCouponBatch.class, creditProduct.getCreditCouponBatchId());
            
            if (creditCouponBatch == null) {
                throw new BusinessException("认领参数异常");
            }
            
            if (!creditCouponBatch.isEffective()) {
                throw new BusinessException("兑换失败：该积分券已失效");
            }
        } else if (creditProduct.getType() == CreditProductType.PRODUCT) {
            if (userAddress == null) {
                throw new BusinessException("地址未选中");
            }
        }

    }
}
